package ProtocolResolution

import (
	"encoding/binary"
	"fmt"
	"lht-go-plugins/LhtLog"
	"lht-go-plugins/LhtPlugins/Sql/sqlite"
	"lht-go-plugins/LhtSettings"
	"math"
	"net"
	"net/http"
	"strconv"
	"strings"
	"sync"
)

/*
	 ======================================================
		通用 UDP 监听结构

======================================================
*/
var OCMessageChannel = make(chan sqlite.OCMessage, 100)
var SqlitePluginInstance sqlite.SqlitePlugin
var hub = NewHub()

type udpReceiver struct {
	conn   *net.UDPConn
	closed bool
	wg     sync.WaitGroup
}

func (r *udpReceiver) Close() {
	r.closed = true
	if r.conn != nil {
		r.conn.Close()
	}
	r.wg.Wait()
}

/* ======================================================
	OC 协议插件
====================================================== */

type OCPlugin struct {
	recv     udpReceiver
	listenIP string
	port     int
}

func NewOCPlugin(listenPort int) *OCPlugin {
	return &OCPlugin{
		listenIP: "0.0.0.0",
		port:     listenPort,
	}
}

func (p *OCPlugin) Name() string { return "OCProtocol" }

func (p *OCPlugin) Init(cfg any) error {
	// 你说暂时不需要配置，这里什么也不做
	return nil
}
func handleWebSocket(w http.ResponseWriter, r *http.Request) {
	UpgradeWebSocket(w, r, hub)
}
func (p *OCPlugin) Start() error {
	SqlitePluginInstance = sqlite.SqlitePlugin{}
	SqlitePluginInstance.Init(&LhtSettings.SqliteConfig{Path: "./drone_data.db"})
	SqlitePluginInstance.Start()
	addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", p.listenIP, p.port))
	if err != nil {
		return err
	}

	p.recv.conn, err = net.ListenUDP("udp", addr)
	if err != nil {
		return err
	}

	// 给无人机发送 start
	remote := &net.UDPAddr{IP: net.ParseIP("192.168.2.2"), Port: 9023}
	p.recv.conn.WriteToUDP([]byte("start"), remote)

	fmt.Println("[OC] Start OK, 监听中…")
	go func() {
		for {
			// 这里用一个 channel 接收（下面会改 OCPlugin）
			msg := <-OCMessageChannel // 我们后面加的全局 channel
			hub.Broadcast(msg)
		}
	}()

	p.recv.wg.Add(1)
	go p.loopRecv()
	// 静态文件服务
	fs := http.FileServer(http.Dir("E:/git/lht-go-plugins/LhtPlugins/Drone/ProtocolResolution/static"))
	http.Handle("/", fs)

	// WebSocket 端点
	http.HandleFunc("/ws", handleWebSocket)

	fmt.Println("服务器启动: http://localhost:8080")
	go http.ListenAndServe(":8080", nil)

	return nil
}

func (p *OCPlugin) Stop() error {
	p.recv.Close()
	fmt.Println("[OC] 已停止")
	return nil
}

func (p *OCPlugin) loopRecv() {
	defer p.recv.wg.Done()

	buf := make([]byte, 2048)

	for !p.recv.closed {
		n, _, err := p.recv.conn.ReadFromUDP(buf)
		if err != nil || n == 0 {
			continue
		}
		p.Recv(buf[:n])
	}
}

// 从字节流读取 float32（小端）
func readFloat32(b []byte) float32 {
	return math.Float32frombits(binary.LittleEndian.Uint32(b))
}
func (p *OCPlugin) Recv(data []byte) bool {
	s := strings.TrimSpace(string(data))
	//println(s)
	if len(s) == 0 {
		return false
	}
	if strings.Contains(s, "start") {
		println("[OC] 收到 start 回复", s)
		return true
	}
	if strings.Contains(s, "ssid") {
		println("[OC] 收到 wifi 回复", s)
		return true
	}
	// 心跳包优先
	if strings.Contains(s, "Heart Beat") {
		return p.parseHeartBeat(s)
	}

	// 先按逗号分段（保留原始段），但后面会把没有 '=' 的段合并回前一个 key 的 value
	rawParts := strings.Split(s, ",")
	kv := buildKVFromCommaParts(rawParts)
	//println(0, kv["drone_GPS"])
	//println(1, kv["home_GPS"])
	//println(2, kv["pilot_GPS"])
	//fmt.Printf("kv = %+v\n", kv)
	msg := sqlite.OCMessage{}

	// device
	if v, ok := kv["device"]; ok {
		if i, err := strconv.ParseUint(v, 10, 32); err == nil {
			msg.Device = uint32(i)
		}
	}

	// serial
	msg.Serial = kv["serial"]

	// model: 73-Mini 3 Pro → modelID=73  modelName="Mini 3 Pro"
	if v, ok := kv["model"]; ok {
		arr := strings.SplitN(v, "-", 2)
		if len(arr) == 2 {
			if i, err := strconv.ParseUint(strings.TrimSpace(arr[0]), 10, 32); err == nil {
				msg.ModelID = uint32(i)
			}
			msg.ModelName = strings.TrimSpace(arr[1])
		} else {
			msg.ModelName = strings.TrimSpace(v)
		}
	}

	// uuid
	msg.UUID = kv["uuid"]

	// GPS 字段（现在应该是完整的 "lon,lat"）
	msg.DroneLon, msg.DroneLat = parseGPS(kv["drone_GPS"])
	msg.HomeLon, msg.HomeLat = parseGPS(kv["home_GPS"])
	msg.PilotLon, msg.PilotLat = parseGPS(kv["pilot_GPS"])

	// float 字段
	msg.Height = parseFloat(kv["Height"])
	msg.Altitude = parseFloat(kv["Altitude"])
	msg.EastV = parseFloat(kv["EastV"])
	msg.NorthV = parseFloat(kv["NothV"])
	msg.UpV = parseFloat(kv["UpV"])
	msg.Freq = parseFloat(kv["freq"])

	// rssi
	msg.Rssi = int32(parseFloat(kv["rssi"]))
	msg.Distance = parseFloat(kv["distance"])
	err := SqlitePluginInstance.Save(&msg)
	if err != nil {
		LhtLog.Error("OCMessage 保存失败" + err.Error())
		return false
	}
	OCMessageChannel <- msg
	fmt.Printf("[OC] 解析成功: %+v\n", msg)
	return true
}

func buildKVFromCommaParts(rawParts []string) map[string]string {
	kv := make(map[string]string)
	var lastKey string

	for i := 0; i < len(rawParts); i++ {
		part := strings.TrimSpace(rawParts[i])
		if part == "" {
			continue
		}

		if strings.Contains(part, "=") {
			// 新的 key=value 段
			parts := strings.SplitN(part, "=", 2)
			key := strings.TrimSpace(parts[0])
			val := ""
			if len(parts) > 1 {
				val = strings.TrimSpace(parts[1])
			}
			kv[key] = val
			lastKey = key
		} else {
			// 没有 '='，当作上一个 key 的 value 的延续（可能是 GPS 的第二个数）
			if lastKey != "" {
				// append with comma to keep "lon,lat" 格式
				prev := kv[lastKey]
				if prev == "" {
					kv[lastKey] = part
				} else {
					kv[lastKey] = prev + "," + part
				}
			}
			// 如果 lastKey == ""，说明报文不规范，直接跳过
		}
	}

	return kv
}
func parseFloat(s string) float32 {
	f, _ := strconv.ParseFloat(s, 32)
	return float32(f)
}

func parseGPS(s string) (float32, float32) {
	arr := strings.Split(s, ",")
	if len(arr) != 2 {
		return 0, 0
	}
	lon, _ := strconv.ParseFloat(strings.TrimSpace(arr[0]), 32)
	lat, _ := strconv.ParseFloat(strings.TrimSpace(arr[1]), 32)
	return float32(lon), float32(lat)

}
func (p *OCPlugin) parseHeartBeat(s string) bool {

	// #=35, device=3547, Heart Beat, 497
	parts := strings.Split(s, ",")
	hb := sqlite.OCHeartBeat{}

	for _, part := range parts {
		part = strings.TrimSpace(part)

		switch {
		case strings.HasPrefix(part, "#="):
			hb.Num = int(parseFloat(strings.TrimPrefix(part, "#=")))

		case strings.HasPrefix(part, "device="):
			hb.DeviceID = int(parseFloat(strings.TrimPrefix(part, "device=")))

		case strings.Contains(part, "Heart Beat"):
			// 跳过此项

		default:
			// 最后一项通常是心跳值
			if v, err := strconv.Atoi(part); err == nil {
				hb.Value = v
			}
		}
	}

	fmt.Printf("[OC] 心跳包解析成功: %+v\n", hb)
	return true
}

/* ======================================================
	信号协议插件（频谱侦测）
====================================================== */

type SignalPlugin struct {
	recv     udpReceiver
	listenIP string
	port     int
}

func NewSignalPlugin(listenPort int) *SignalPlugin {
	return &SignalPlugin{
		listenIP: "0.0.0.0",
		port:     listenPort,
	}
}

func (p *SignalPlugin) Name() string { return "SignalProtocol" }

func (p *SignalPlugin) Init(cfg any) error { return nil }

func (p *SignalPlugin) Start() error {
	SqlitePluginInstance = sqlite.SqlitePlugin{}
	SqlitePluginInstance.Init(&LhtSettings.SqliteConfig{Path: "./drone_data.db"})
	SqlitePluginInstance.Start()
	addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", p.listenIP, p.port))
	if err != nil {
		return err
	}

	p.recv.conn, err = net.ListenUDP("udp", addr)
	if err != nil {
		return err
	}

	remote := &net.UDPAddr{IP: net.ParseIP("192.168.2.1"), Port: 9024}
	p.recv.conn.WriteToUDP([]byte("start"), remote)

	fmt.Println("[Signal] Start OK, 监听中…")

	p.recv.wg.Add(1)
	go p.loopRecv()

	return nil
}

func (p *SignalPlugin) Stop() error {
	p.recv.Close()
	fmt.Println("[Signal] 已停止")
	return nil
}

func (p *SignalPlugin) loopRecv() {
	defer p.recv.wg.Done()

	buf := make([]byte, 2048)

	for !p.recv.closed {
		n, _, err := p.recv.conn.ReadFromUDP(buf)
		if err != nil || n == 0 {
			continue
		}
		p.Recv(buf[:n])
	}
}

func (p *SignalPlugin) Recv(data []byte) bool {

	s := strings.TrimSpace(string(data))
	if len(s) == 0 {
		return false
	}

	if !strings.Contains(s, "device=") || !strings.Contains(s, "gpio=") {
		// start 应答、心跳、ssid 等其他包在这里直接放行或处理
		if strings.Contains(s, "start") {
			println("[Signal] 收到 start 回复:", s)
			return true
		}
		println("[Signal] 收到数据:", s)
		return false
	}

	startIdx := strings.Index(s, "device=")
	endIdx := strings.LastIndex(s, "gpio=")
	if startIdx == -1 || endIdx == -1 || endIdx <= startIdx {
		return false
	}

	gpioSegmentEnd := strings.Index(s[endIdx:], ",")
	if gpioSegmentEnd == -1 {
		gpioSegmentEnd = len(s) // 到结尾
	} else {
		gpioSegmentEnd += endIdx
	}

	validPart := s[startIdx:gpioSegmentEnd] // 这段才是干净的 KV 数据

	// 3. 复用你 OCPlugin 已经写得完美的工具函数
	rawParts := strings.Split(validPart, ",")
	kv := buildKVFromCommaParts(rawParts)

	// 4. 解析到结构体
	msg := sqlite.SignalMessage{}

	if v, ok := kv["device"]; ok {
		if i, err := strconv.ParseUint(v, 10, 32); err == nil {
			msg.Device = uint32(i)
		}
	}

	if v, ok := kv["model"]; ok {
		msg.Model = v
	}

	msg.Freq = parseFloat(kv["freq"])       // MHz，如 5790.0
	msg.Rssi = parseFloat(kv["rssi"])       // dBm
	msg.Seq = uint32(parseFloat(kv["seq"])) // seq 通常不大

	if v, ok := kv["gpio"]; ok {
		if i, err := strconv.ParseUint(v, 10, 32); err == nil {
			msg.GPIO = uint32(i)
		}
	}
	err := SqlitePluginInstance.Save(&msg)
	if err != nil {
		LhtLog.Error("OCMessage 保存失败" + err.Error())
		return false
	}
	fmt.Printf("[Signal] 解析成功: Device=%d Model=%s Freq=%.1fMHz RSSI=%.1fdBm Seq=%d GPIO=0x%X \n",
		msg.Device, msg.Model,
		msg.Freq, msg.Rssi,
		msg.Seq, msg.GPIO)

	return true
}
